package com.mgg.payment.controller.ali;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Map;

import com.mgg.common.dto.OrderDTO;
import com.mgg.common.enums.OrderPayWayEnum;
import com.mgg.common.enums.OrderStatusEnum;
import com.mgg.common.util.ResultVOUtil;
import com.mgg.payment.config.AlipayAccountConfig;
import com.mgg.payment.enums.PaymentResultEnum;
import com.mgg.payment.service.account.AccountService;
import com.mgg.payment.service.alipay.AliPayService;
import com.mgg.payment.service.order.RefundOrderService;
import com.mgg.payment.service.order.SalesOrderService;
import com.mgg.payment.service.pay.PaymentService;
import com.mgg.payment.util.MathUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alipay.api.response.AlipayTradeAppPayResponse;

@RestController
public class AliPayController {

	private Logger log = LoggerFactory.getLogger(getClass());

	@Autowired
    private SalesOrderService orderService;

	@Autowired
    private AccountService accountService;
	
    @Autowired
    private AliPayService aliPayService;
    
    @Autowired
    private AlipayAccountConfig alipayAccountConfig;
    
    @Autowired
    private PaymentService paymentService;
    
	/**
	 * 发起支付
	 * @throws Exception 
	 */
	@GetMapping(value = "/ali/create")
	public Object pay(@RequestParam("orderId") String orderId) throws Exception {
        OrderDTO order = orderService.getOrderByOrderId(orderId);
        if (order == null) {
			return ResultVOUtil.error(PaymentResultEnum.ORDER_NOT_EXIST);
        }
        if(order.getStatus() != OrderStatusEnum.UN_PAY.getCode()) {
            return ResultVOUtil.error(PaymentResultEnum.ORDER_STATUS_ERROR);
		}

        AlipayTradeAppPayResponse response = aliPayService.create(orderId, order.getOrderTotal());
        System.out.println(response);
        if (!response.isSuccess()) {
        	log.error("【阿里支付】发起支付, 发起支付失败, 网关返回码={}, 网关返回码描述={}, 业务返回码={}, 业务返回码描述={}, orderId={}", 
    				response.getSubCode(), response.getSubMsg(), response.getCode(), response.getMsg(), orderId);
			return ResultVOUtil.error(PaymentResultEnum.ALIPAY_CREATE_ERROR);
    	}
        return ResultVOUtil.success(response.getBody());
	}

	/**
	 * 异步回调
	 */
	@Transactional
	@PostMapping(value = "/ali/notify")
	public Object notify(@RequestParam Map<String, Object> requestParams) throws Exception {
		String tradeStatus = requestParams.get("trade_status").toString();
		if (!Arrays.asList("TRADE_FINISHED","TRADE_SUCCESS").contains(tradeStatus)) {
			return "failure";
		}
		if (!aliPayService.notify(requestParams)) {
			return "failure";
		}
		
		// 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号
		String orderId = requestParams.get("out_trade_no").toString();
		OrderDTO order = orderService.getOrderByOrderId(orderId);
        if (order == null) {
        	log.error("【支付宝支付】异步通知, 订单不存在, orderId={}", orderId);
        	return "failure";
        }
        if(order.getStatus() != OrderStatusEnum.UN_PAY.getCode()) {
            log.error("【支付宝支付】异步通知, 订单状态错误, orderId={}", orderId);
            return "failure";
        }
		
		// 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额）
		BigDecimal totalAmount  = new BigDecimal(requestParams.get("total_amount").toString());
		if (!MathUtils.equals(totalAmount.doubleValue(), order.getOrderTotal().doubleValue())) {
            log.error("【支付宝支付】异步通知, 订单金额不一致, orderId={}, 通知金额={}, 系统金额={}",
            		orderId, totalAmount, order.getOrderTotal());
            return "failure";
        }
				
		// 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
		String sellerEmail = requestParams.get("seller_email").toString();			
		if (!"hyling@gzqqs.com".equals(sellerEmail)) {
			log.error("【支付宝支付】异步通知, 卖家支付宝账号不一致, 通知seller_email={}, 系统seller_email={}", sellerEmail, "hyling@gzqqs.com" );
            return "failure";
		}
		
		// 4、验证app_id是否为该商户本身
		String appId = requestParams.get("app_id").toString();
		if (!alipayAccountConfig.getAppId().equals(appId)) {
			log.error("【支付宝支付】异步通知, app_id不一致, 通知app_id={}, 系统app_id={}", appId, alipayAccountConfig.getAppId());
            return "failure";
		}
		
		// 上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，
		//	并且过滤重复的通知结果数据。在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
		paymentService.paySuccess(order, OrderPayWayEnum.ALI.getCode(), requestParams.get("trade_no").toString());
		return "success";
	}
}
